package com.insight.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

/**
 * T109: 表关系实体类
 * 记录数据库表之间的外键关系
 *
 * @author Insight Team
 */
@Entity
@Table(name = "table_relationship",
        uniqueConstraints = @UniqueConstraint(columnNames = {"source_table_id", "constraint_name"}),
        indexes = {
                @Index(name = "idx_relationship_source", columnList = "source_table_id"),
                @Index(name = "idx_relationship_target", columnList = "target_table_id"),
                @Index(name = "idx_relationship_constraint", columnList = "constraint_name")
        })
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TableRelationship {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 源表(子表,包含外键的表)
     */
    @NotNull(message = "源表不能为空")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "source_table_id", nullable = false)
    @JsonIgnoreProperties({"dataSource", "hibernateLazyInitializer", "handler"})
    private MetadataTable sourceTable;

    /**
     * 目标表(父表,被引用的表)
     */
    @NotNull(message = "目标表不能为空")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "target_table_id", nullable = false)
    @JsonIgnoreProperties({"dataSource", "hibernateLazyInitializer", "handler"})
    private MetadataTable targetTable;

    /**
     * 外键约束名称
     */
    @NotNull(message = "约束名称不能为空")
    @Size(max = 200, message = "约束名称长度不能超过200")
    @Column(name = "constraint_name", nullable = false, length = 200)
    private String constraintName;

    /**
     * 源表的外键列(多列用逗号分隔)
     */
    @NotNull(message = "源列不能为空")
    @Size(max = 500, message = "源列长度不能超过500")
    @Column(name = "source_column", nullable = false, length = 500)
    private String sourceColumn;

    /**
     * 目标表的主键列(多列用逗号分隔)
     */
    @NotNull(message = "目标列不能为空")
    @Size(max = 500, message = "目标列长度不能超过500")
    @Column(name = "target_column", nullable = false, length = 500)
    private String targetColumn;

    /**
     * 关系类型(FOREIGN_KEY, UNIQUE, etc.)
     */
    @Column(name = "relation_type", length = 50)
    private String relationType;

    /**
     * ON DELETE规则(CASCADE, SET NULL, RESTRICT, NO ACTION)
     */
    @Column(name = "on_delete_rule", length = 50)
    private String onDeleteRule;

    /**
     * ON UPDATE规则(CASCADE, SET NULL, RESTRICT, NO ACTION)
     */
    @Column(name = "on_update_rule", length = 50)
    private String onUpdateRule;

    /**
     * 关系描述(业务语义)
     */
    @Column(name = "description", length = 1000)
    private String description;

    /**
     * 记录创建时间
     */
    @CreationTimestamp
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    /**
     * 记录更新时间
     */
    @UpdateTimestamp
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;

    /**
     * 生命周期回调: 持久化之前
     * 设置默认值
     */
    @PrePersist
    public void prePersist() {
        if (this.relationType == null) {
            this.relationType = "FOREIGN_KEY";
        }
        if (this.onDeleteRule == null) {
            this.onDeleteRule = "NO ACTION";
        }
        if (this.onUpdateRule == null) {
            this.onUpdateRule = "NO ACTION";
        }
    }

    /**
     * 业务方法: 获取关系的完整描述
     *
     * @return 格式: source_table.source_column -> target_table.target_column
     */
    public String getFullDescription() {
        if (sourceTable != null && targetTable != null) {
            return String.format("%s.%s -> %s.%s",
                    sourceTable.getTableName(),
                    sourceColumn,
                    targetTable.getTableName(),
                    targetColumn);
        }
        return String.format("%s -> %s", sourceColumn, targetColumn);
    }

    /**
     * 业务方法: 判断是否为复合外键
     *
     * @return true if 源列或目标列包含多列
     */
    public boolean isCompositeKey() {
        return sourceColumn != null && sourceColumn.contains(",");
    }
}
